package cn.itcast.dewu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.itcast.dewu.dto.*;
import cn.itcast.dewu.pojo.Follow;
import cn.itcast.dewu.pojo.UserInfo;
import cn.itcast.dewu.service.FollowService;
import cn.itcast.dewu.service.GoodsService;
import cn.itcast.dewu.service.UserInfoService;
import cn.itcast.dewu.utils.RedisIdWork;
import cn.itcast.dewu.utils.RegexUtils;
import cn.itcast.dewu.utils.UserHolder;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.itcast.dewu.pojo.User;
import cn.itcast.dewu.service.UserService;
import cn.itcast.dewu.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpSession;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.itcast.dewu.utils.RedisConstants.*;

/**
 * @author Administrator
 * @description 针对表【tb_user】的数据库操作Service实现
 * @createDate 2022-04-29 14:06:30
 * <p>
 * 登录功能实现
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisIdWork idWork;
    @Autowired
    private UserInfoService userInfoService;

    /*
     * 发送验证码并保存验证码
     * */
    @Override
    public Result sendCode(LoginFormDTO loginFormDTO) {
        //使用工具类校验验证码是否符合规则
        if (RegexUtils.isPhoneInvalid(loginFormDTO.getPhone())) {
            //不符合
            return Result.fail("填写的手机号不符合规则^_^");
        }
        if (RegexUtils.isEmailInvalid(loginFormDTO.getEmail())) {
            return Result.fail("填写的邮箱不符合规则^_^");
        }

        //符合生成随机的6位验证码
        String code = RandomUtil.randomNumbers(6);
        //将验证码保存到redis中并设置过期时间
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + loginFormDTO.getPhone(), code, LOGIN_CODE_TTL, TimeUnit.MINUTES);
        JavaEmailDTO emailDTO = new JavaEmailDTO();
        emailDTO.setEmail(loginFormDTO.getEmail()).setCode(code);
        rabbitTemplate.convertAndSend("java.mail.exchange","java.mail",emailDTO);
        //发送验证码,这里用日志记录一下信息
        log.debug("你的验证码信息为:" + code);
        //
        //返回ok
        return Result.ok();
    }


    /*
     * 登录功能,即为对验证码进行判断
     * */
    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {
        //点击登录按钮的时候再次判断一下是否修改了手机号
        if (RegexUtils.isPhoneInvalid(loginForm.getPhone())) {
            return Result.fail("请填写正确的手机号^_^");
        }
        if (RegexUtils.isEmailInvalid(loginForm.getEmail())) {
            return Result.fail("请填写正确的邮箱");
        }
        //一致从数据库中查询用户
        User user = query().eq("phone", loginForm.getPhone()).one();

        //判断数据库中是否存在该用户
        if (user == null) {
            //数据库中无该用户则创建该用户
            return Result.fail("请先注册^_^",false);
        }
        if (user.getEmail().equals(loginForm.getEmail())) {
            return Result.fail("请输入你自己的邮箱^_^");
        }

        String code = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + loginForm.getPhone());
        //判断填写的手机号与redis中的手机号是否一致

        if (loginForm.getCode() == null || code == null || !code.equals(loginForm.getCode())) {
            //不一致
            return Result.fail("请填写正确的验证码^_^");
        }

        //将用户信息保存到redis中
        String token = UUID.randomUUID().toString(true);
        // 将User对象转为HashMap存储
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true) //忽略空值
                        .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
        //存储
        String tokenKey = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);
        //设置token有效期
        stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);

        //返回token
        return Result.ok(token);
    }


    //创建可显示的用户信息
    private User createUserWithPhoneAndPassword(String phone,String password,String email) {
        User user = new User();
        long userid = idWork.nextID("user");
        user.setId(userid);
        user.setPhone(phone);
        user.setIcon("http://rb1oc9tg0.hn-bkt.clouddn.com/dewu/QQ%E5%9B%BE%E7%89%8720220429142642.jpg");
        user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
        user.setPassword(password);
        user.setEmail(email);
        //保存用户
        save(user);

        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(userid);
        userInfoService.save(userInfo);
        return user;
    }

    /*
     * 登出功能
     * */
    @Override
    public Result logout(String token) {
        System.out.println(token);
        if (StrUtil.isEmpty(token)) {
            return Result.fail("你已经退出^_^");
        }
        Boolean falg = stringRedisTemplate.delete(LOGIN_USER_KEY + token);
        if (BooleanUtil.isTrue(falg)) {
            return Result.ok("退出登录成功^_^");
        }
        return Result.fail("退出失败^_^,请重试!");
    }

    @Override
    public Result me() {
        //获取到当前登录的id
        UserDTO user = UserHolder.getUser();
        Long userId = user.getId();
//        Integer count = goodsService.query().eq("user_id", userId).count();
        UserInfo userInfo = userInfoService.query().eq("user_id", userId).one();

        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setId(userId).setIcon(user.getIcon())
                .setNickName(user.getNickName())
                .setFans(userInfo.getFans())
                .setFollowee(userInfo.getFollowee())
                .setIntroduce(userInfo.getIntroduce());
        return Result.ok(userInfoDTO);
    }


    /*
     *
     * 查看所有关注
     * */
    @Autowired
    private FollowService followService;

    @Override
    public Result getFollowee(Long userId) {
        List<UserDTO> userDTOS = getUserDTOS(userId, "user_id");
        return Result.ok(userDTOS);
    }

    /*
    * 查看所有粉丝
    * 0*/
    @Override
    public Result getFans(Long userId) {
        List<UserDTO> userDTOS = getUserDTOS(userId, "follow_user_id");
        return Result.ok(userDTOS);
    }

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Override
    public Result resUserPassword(LoginFormDTO loginForm) {
        //点击登录按钮的时候再次判断一下是否修改了手机号
        if (RegexUtils.isPhoneInvalid(loginForm.getPhone())) {
            return Result.fail("请填写正确的手机号^_^");
        }

        //判断填写的手机号与redis中的手机号是否一致
        String code = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + loginForm.getPhone());
        if (loginForm.getCode() == null || code == null || !code.equals(loginForm.getCode())) {
            //不一致
            return Result.fail("请填写正确的验证码^_^");
        }
        //一致从数据库中查询用户
        User user = query().eq("phone", loginForm.getPhone()).one();
        //判断数据库中是否存在该用户

        if (user == null) {
            //数据库中无该用户则创建该用户
            createUserWithPhoneAndPassword(loginForm.getPhone(),loginForm.getPassword(),loginForm.getEmail());
        } else{
            return Result.fail("你已经注册过了^_^");
        }

        return Result.ok("注册成功^_^");
    }
    /*
    * 根据密码登录
    * */
    @Override
    public Result loginByPassword(LoginFormDTO loginForm) {
        //点击登录按钮的时候再次判断一下是否修改了手机号
        if (RegexUtils.isPhoneInvalid(loginForm.getPhone())) {
            return Result.fail("请填写正确的手机号^_^");
        }

        //一致从数据库中查询用户
        User user = query().eq("phone", loginForm.getPhone()).one();
        //判断数据库中是否存在该用户
        if (user == null) {
            //数据库中无该用户则创建该用户
            return Result.fail("请先注册^_^",false);
        }
        String password = user.getPassword();
        if (!loginForm.getPassword().equals(password)) {
            return Result.fail("密码错误奥^_^");
        }
        //将用户信息保存到redis中
        String token = UUID.randomUUID().toString(true);
        // 将User对象转为HashMap存储
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true) //忽略空值
                        .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
        //存储
        String tokenKey = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);
        //设置token有效期
        stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);

        //返回token
        return Result.ok(token);
    }


    private List<UserDTO> getUserDTOS(Long userId, String follow_user_id) {
        List<Follow> follows = followService.query().eq(follow_user_id, userId).list();
        if (follows.isEmpty()) {
            //如果没有关注 范湖空集合
            return Collections.emptyList();
        }
        List<Long> followUserId =
                follows.stream().
                        map(follow -> follow.getFollowUserId()).collect(Collectors.toList());
        List<User> users = query().in("id", followUserId).list();
        //将user转换成userDto返回
        return users.stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
    }
}




